/*!
    \copyright  Copyright (c) 2021-2024 Qualcomm Technologies International, Ltd.
                All Rights Reserved.
                Qualcomm Technologies International, Ltd. Confidential and Proprietary.
    \file
    \defgroup   media_control_client Media Control Client
    @{
    \ingroup    profiles
    \brief      Header file for Media control profile client
*/

#ifndef MEDIA_CONTROL_CLIENT_H
#define MEDIA_CONTROL_CLIENT_H

#ifdef USE_SYNERGY

#include "mcp_mcs_common.h"
#include "bt_types.h"
#include "audio_sources.h"
#include "mcp.h"

#ifdef INCLUDE_GATT_OTS_CLIENT_MODULE

/*! \brief Structure to send received data using OTS callack */
typedef struct
{
    gatt_cid_t                cid;               /*! GATT Connection id for which response from OTS server is received */
    McpMessageId              id;                /*! MCP message id of requested OTS service */
    McpStatus                 status;            /*! Status of service requested */
    GattOtscObjectId          objectId;          /*! Object id received for the requested service */
    GattOtscDeviceType        modifier;          /*! Device[Another Client/Server] which made the change */
    GattOtscObjectChangeType  changeType;        /*! Kind of change occurred at server */
    bool                      moreToCome;        /*! TRUE if more data to come. False otherwise */
    uint16                    data_length;       /*! Length of data received */
    uint8                     *data;             /*! Data received for the requested service. Data shall be copied in callback if required for later processing */
} media_control_client_ots_callback_msg_t;

/*! \brief Callback structure used when an observer registers with Object Transfer Service.
    \param[out] media_control_client_ots_callback_msg            Structure to send received data using OTS callack
 */
typedef void (*media_control_client_ots_callback_t)(media_control_client_ots_callback_msg_t ots_callback_msg);

#endif /* INCLUDE_GATT_OTS_CLIENT_MODULE */

/*! \brief Initialise the Media control client component
 */
void MediaControlClient_Init(void);

/*! \brief Function to send the MCS Opcode to GMCS server.
    \param[in] cid    GATT Connection id to which the play/pause opcode to send.If connection
                      id is invalid, this function will send the play/pause opcode to all 
                      connected media servers.
    \param[in] op     MCS client control opcode to be sent to remote MCS server.
    \param[in] val    value to be associated with the opcode(not all opcodes will have value).
 */
void MediaControlClient_SendMediaControlOpcode(gatt_cid_t cid, GattMcsOpcode op, int32 val);

/*! \brief Funtion which returns the audio provider context based on the current media state.
    \return Audio provider context
*/
audio_source_provider_context_t MediaClientControl_GetAudioSourceContext(gatt_cid_t cid);

/*! \brief Checks the local media state and sends either Play/Pause opcode to remote server.
    \param[in] cid  GATT Connection id on which the play/pause will be applied.If connection
                    id is invalid, this function will send the play/pause opcode to all 
                    connected media servers.
    \return
 */
void MediaControlClient_TogglePlayPause(gatt_cid_t cid);

/*! \brief Read the media player attribute.
    \param[in] cid    GATT Connection id on which the attribute has to be read.
    \param[in] charac Attribute to read.
 */
void MediaControlClient_GetMediaPlayerAttribute(gatt_cid_t cid, MediaPlayerAttribute charac);

/*! \brief Read the cached media player attribute.
    \param[in] cid    GATT Connection id on which the attribute has to be read.
    \param[in] charac Attribute to read.
    \param[out] pp_data  Encoded allocated data will be returned in this variable. Caller needs to free the memory

    \return 0 if encoding failed, else length of the data.
 */
uint16 MediaControlClient_GetCachedMediaPlayerAttribute(gatt_cid_t cid, MediaPlayerAttribute charac, uint8 **pp_data);

/*! \brief Set the media player attribute.
    \param[in] cid     GATT Connection id on which the attribute has to be set.
    \param[in] charac  Attribute to write to.
    \param[in] len     Len of the value to be written
    \param[in] val     Value to write.
 */
void MediaControlClient_SetMediaPlayerAttribute(gatt_cid_t cid,
                                                MediaPlayerAttribute charac,
                                                uint16 len,
                                                uint8 *val);

/*! \brief Register for media notifications
    \param[in] cid         GATT Connection id on which the notification has to be enabled.
    \param[in] characType  Bitmask of MCS characteristics 
    \param[in] notif_value Bitmask to enable/disable respective characteristics CCCD.
 */
void MediaControlClient_RegisterForNotifications(gatt_cid_t cid,
                                                 MediaPlayerAttributeMask characType,
                                                 uint32 notif_value);

/*! \brief Check if the Media control service is available in remote server and the set the service status accordingly.
    \param[in] cid    GATT Connection id on which the service status needs to be set
    \param[in] service_not_found TRUE if we clearly knows the MCS service/ MCS client role is not present in the remote server.
                                 FALSE if we want media control client to check whether MCS service is there or not in
                                 remote server and set the status accordingly.
 */
void MediaControlClient_SetServiceStatusForCid(gatt_cid_t cid, bool service_not_found);

/*! \brief Check if the Media control service is available in remote server and is discovered */
#define MediaControlClient_ConnectProfile(cid)      MediaControlClient_SetServiceStatusForCid(cid, FALSE)

/*! \brief Get the content control id for media control client
    \param[in] cid    GATT Connection id to which the content control id is to read.

    \return Content control id of the media control client
 */
uint8 MediaClientControl_GetContentControlId(gatt_cid_t cid);

/*! \brief Register the Media control client component with the Device Database Serialiser */
void MediaControlClient_RegisterAsPersistentDeviceDataUser(void);

/*! \brief Return the device for the audio source */
device_t MediaClientControl_GetDeviceForAudioSource (audio_source_t source);


/*! \brief Callback interface defined for the clients to receive MCP state change indications
    \param[in] media_state  Value to indicate new MCP media state
    \param[in] cid  CID value for the connected device
*/
typedef struct
{
    void (*media_state_change_callback)(uint8 media_state, gatt_cid_t cid);

} media_control_client_callback_if;

/*! \brief Register to receive media state change indications
    \param[in] callback_if  Pointer to the structure of type media_control_client_callback_if
 */
void mediaControlClient_RegisterForMediaStateChangeIndications(media_control_client_callback_if * callback_if);

/*! \brief check if MCP is connected(to be called only on primary)
    \return true if MCP connected, false otherwise(false on secondary)
*/
bool MediaClientControl_IsMcpConnected(void);

/*! \brief Check if MCP instance corrosponding to cid
    \param[in] cid GATT Connection id for which instance validity to be checked.

    \return TRUE if valid MCP instance is there for cid
 */
bool MediaClientControl_IsConnected(gatt_cid_t cid);

#ifdef INCLUDE_GATT_OTS_CLIENT_MODULE

/*! \brief Read object by id from server for requested characteristics.
    \param[in] cid                 GATT Connection id on which the attribute has to be read.
    \param[in] charac              Attribute to read.
    \return                        TRUE if request send is successful, otherwise FALSE
 */
bool MediaControlClient_GetOtsObjectByObjectId(gatt_cid_t cid, MediaPlayerAttribute characType);

/*! \brief Request to start object discover.
    \param[in] cid                 GATT Connection id on which the discover has to be started.
    \param[in] objMetadataType     Metadata type to read.
    \return                        TRUE if request send is successful, otherwise FALSE
 */
bool MediaControlClient_McpStartDiscoverAllObjectReq(gatt_cid_t cid, McpObjectMetadataType objMetadataType);

/*! \brief Request to stop object discover.
    \param[in] cid                 GATT Connection id on which the discover has to be stopped.
    \return                        TRUE if request send is successful, otherwise FALSE
 */
bool MediaControlClient_McpStopDiscoverAllObjectReq(gatt_cid_t cid);

/*! \brief Request to read current media object metadata.
    \param[in] cid                 GATT Connection id on which the metadata has to be read.
    \param[in] objMetadataType     Metadata type to read.
    \return                        TRUE if request send is successful, otherwise FALSE
 */
bool MediaControlClient_GetCurrentMediaObjectMetadata(gatt_cid_t cid, McpObjectMetadataType objMetadataType);

/*! \brief Register for Object change indication.
    \param[in] cid                 GATT Connection id on which the indication has to be enabled or disabled.
    \param[in] charValsMask        Enable or disable object change indication.
    \return                        TRUE if register send is successful, otherwise FALSE
 */
bool MediaControlClient_RegisterForObjectChangedInd(gatt_cid_t cid, GattOtscCharacValuesMask charValsMask);

/*! \brief Request to abort current object data transfer.
    \param[in] cid                 GATT Connection id on which the abort has to be done.
    \return                        TRUE if request send is successful, otherwise FALSE
 */
bool MediaControlClient_McpAbortOtsProcedureReq(gatt_cid_t cid);

/*! \brief Register OTS callback.
    \param[in] handler             Handler to be used for receiving response from OTS server.
 */
void MediaControlClient_RegisterOtsClientCallback(media_control_client_ots_callback_t handler);

#endif /* INCLUDE_GATT_OTS_CLIENT_MODULE */

#else /* USE_SYNERGY */

#define MediaControlClient_Init()
#define MediaControlClient_SendMediaControlOpcode(cid, op, val)
#define MediaControlClient_GetMediaPlayerAttribute(cid, charac)
#define MediaControlClient_SetMediaPlayerAttribute(cid, charac, len, val)
#define MediaControlClient_RegisterForNotifications(cid, characType, notif_value)
#define MediaClientControl_GetAudioSourceContext(cid) (0)
#define MediaControlClient_RegisterAsPersistentDeviceDataUser()

#endif /* USE_SYNERGY */

#endif /* MEDIA_CONTROL_CLIENT_H */

/*! @} */
